<?php
class Person{
    public $name;
    public function __construct($name)
    {
        $this->name = $name;
    }
}

interface Module{
    function execute();
}

class FtpModule implements Module{
    public function setHost($host){
        print "FtpModule::setHost():$host\n";
    }

    public function setUser($user){
        print "FtpModule::setUser():$user\n";
    }

    public function execute()
    {
        // TODO: Implement execute() method.
    }
}

class PersonModule implements Module{
    public function setPerson(Person $person){
        print "PersonModule::setPerson():{$person->name}";
    }

    public function execute()
    {
        // TODO: Implement execute() method.
    }
}

class ModuleRunner{
    private $configData = array(
        'PersonModule'=>array('person'=>'bob'),
        'FtpModule'=>array('host'=>'example.com','user'=>'anon')
    );
    private $modules = array();

    function init(){
        $interFace = new ReflectionClass('Module');
        foreach($this->configData as $moduleName => $params){
            $module_class = new ReflectionClass($moduleName);
            if(!$module_class->isSubclassOf($interFace)){ //确保类属于model类型
                throw new Exception('不是module类型：'.$moduleName);
            }
            $module = $module_class->newInstance(); //创建一个实例 newInstance可以放任意数量的参数，参数会放当实例化对象的参数
            foreach($module_class->getMethods() as $method){
                $this->handleMethod($module,$method,$params);
            }
        }
        array_push($this->modules,$module);
    }

    public function handleMethod($module,$method,$params){
        $name = $method->getName();
        $args = $method->getParameters();
        if(count($args) != 1 || substr($name,0,3) != 'set'){
            return false;
        }
        $property = strtolower(substr($name,3));
        if(!isset($params[$property])){
            return false;
        }
        var_dump($args);
        $arg_class = $args[0]->getClass();

        if(empty($arg_class)){
            $method->invoke($module,$params[$property]);
        }else{
            $method->invoke($module,$arg_class->newInstance($params[$property]));
        }
    }
}

$test = new ModuleRunner();
$test->init();